Skip to content

fix: dev → main — 快速双击 ESC 可靠中断 + DAG extend 跨 condition-skipped 依赖 reopen - #176

Merged
LeXwDeX merged 5 commits into
mainfrom
dev
Aug 5, 2026
Merged

fix: dev → main — 快速双击 ESC 可靠中断 + DAG extend 跨 condition-skipped 依赖 reopen#176
LeXwDeX merged 5 commits into
mainfrom
dev

Conversation

@LeXwDeX

@LeXwDeX LeXwDeX commented Aug 5, 2026

Copy link
Copy Markdown
Owner

dev → main 集成(全量测试门禁:Typecheck + Unit Tests + E2E linux/windows)。仅含两个 bug 修复,无其他内容。

1. fix(tui): interrupt reliably on fast ESC double-press (#174)

问题:快速双击 ESC 有时无法中断会话,footer 只在 "esc interrupt" / "esc again to interrupt" 之间切换,abort 从未发出。

根因:opentui 解析器在同一次 stdin read 内收到两个 ESC 字节(`\x1b\x1b`,20ms pending 窗口内的终端批处理/高负载 read 合并)时,将其解析为单个 `{name:"escape", meta:true}` 事件;keymap 匹配 ID 编码全部修饰位,与裸 `escape` 绑定不等 → 第二击被静默丢弃,两击计数器永远到不了 2。

修复

  • `session_interrupt` 默认键增加 `alt+escape` 兜底绑定(精确匹配合并事件)
  • meta 修饰的 escape 事件计为"已确认的第二击"(+2 直达中断):TUI prompt 与 run 模式 footer 两条链路(`mergedDoublePress`)
  • 5s 复位定时器改为重 arm 而非叠加,组件卸载经 onCleanup 清理
  • 慢速双击(两次独立事件)原两击确认语义不变
  • 新增 keymap 绑定注册回归测试

验证:tui 全量 238 pass;opencode test/cli/run 199 pass;keymap 回归测试 3 pass。上游同族 issue:anomalyco/opencode #811 / #22629 / #10867。注:该问题为时序竞态(依赖终端字节批处理时机),无法按需手动复现;新版二进制已确认含修复签名串。

2. fix(dag): reopen completed workflow for extend past condition-skipped dependents (#175)

问题:agent 按文档契约(Verdict Disposal Contract:reporting leaf checkpoint 自然完成图后 extend 有效)对 completed 工作流调用 `workflow(action=extend)`,被 `Cannot transition from terminal state ... (completed -> replan)` 误拒,被迫新建重复工作流。

根因:`_extend.hasReportingLeafCheckpoint` 用静态 config 拓扑判 leaf,忽略运行时终态。生产场景(dag_0343f5b05):checkpoint `audit-module-wave`(completed+wakeEligible+report_to_parent)的配置下游 `wire-modules` 运行时 SKIPPED(condition_false)、整链 orphan_cascade——图事实止于 reporting leaf,但静态判定误认为非 leaf → reopenCompleted=false。projector 的 reopen 机制(completed→running)本身齐全,仅被此误判挡住。

修复

  • leaf 判定改用运行时拓扑:SKIPPED(从未执行)依赖不阻塞 checkpoint 资格;COMPLETED/FAILED(实际执行过)依赖仍阻塞
  • extend 失败归因 `extend` 而非误导性的 `replan`;`TerminalViolationError` 携带具体拒绝原因,覆盖全部终态路径(completed 详述四种 / failed / cancelled / archived)
  • workflow 工具 extend 分支补恢复指引(与 replan 分支 catchIf 对齐),提取共享 helper `withTerminalRecovery`
  • 新增 2 个集成测试:condition-skipped 依赖可 reopen(复现生产拓扑)+ 执行过的依赖保持终态

端到端验证(新版程序实测):回归 workflow checkpoint(reporting leaf)+condition-false 下游 → completed → `extend` 成功(Added: repair)→ repair 节点实际执行并完成 → 再次 completed 并唤醒父会话。test/dag 327 pass;core dag 89 pass。

CI 要求

dev→main 需通过 Typecheck + Unit Tests (linux) + E2E Tests (linux & windows)。

LeXwDeX and others added 5 commits August 4, 2026 21:40
Terminals can deliver a fast ESC double-press as a single meta-modified escape event (the parser merges \x1b\x1b within its 20ms pending window), and keymap stroke matching encodes modifiers — the merged event never matched the bare escape binding, so the second press was silently dropped and the two-press counter stalled at 1 (footer toggling between "esc interrupt" and "esc again to interrupt" forever, abort never fired).

- session_interrupt default now binds escape plus an alt+escape fallback
- a meta-modified escape event counts as the confirmed second press in both the TUI prompt and the run-mode footer
- the 5s interrupt-reset timer is re-armed instead of stacking, and cleared on component cleanup
- slow double-press keeps the original two-press confirmation semantics
- adds a keymap binding-registration regression test
… dependents

_extend qualified reporting-leaf checkpoints on the static config topology, so a naturally completed workflow whose checkpoint dependent was condition-skipped (never executed) could not be reopened by an additive extend. The agent followed the documented Verdict Disposal Contract and was rejected with the misleading "completed -> replan" error, then fell back to spawning fresh duplicate workflows.

- leaf qualification now runs on the runtime topology: skipped dependents (condition_false / orphan_cascade) never block the checkpoint; completed/failed dependents still do
- extend rejections are attributed to extend instead of replan, and TerminalViolationError carries the concrete denial reason for every terminal status (completed / failed / cancelled / archived)
- the workflow tool extend branch surfaces recovery guidance like the replan branch
- adds reopen integration tests: condition-skipped dependent reopens; executed dependent keeps the workflow terminal
…n lint ratchet

The reopen guard introduced four no-unsafe-enum-comparison warnings plus one no-unsafe-type-assertion (string row status cast to WorkflowStatus), pushing the merged PR over the oxlint ratchet. Runtime row readers compare statuses as string literals elsewhere (loop.ts); adopt the same convention in the _extend reopen block so the diff adds zero warnings.
fix(tui): interrupt reliably on fast ESC double-press
fix(dag): reopen completed workflow for extend past condition-skipped dependents
@LeXwDeX
LeXwDeX merged commit b8129ab into main Aug 5, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant